import axios from "axios";
import type {
  RequestOptions,
  FullExpandRequestConfig,
  RequestParams,
  ExpandRequestConfig,
} from "./types";
import { axiosRequestConfig } from "./config";
import { RequestMethodEnum } from "@/enums/httpEnum";

import type { AxiosInstance } from "axios";

class Request {
  private axiosRequestConfig: FullExpandRequestConfig; // 私有变量
  private axiosInstance: AxiosInstance; // 私有变量
  // {url:"xxx"}
  constructor(options: RequestOptions = {}) {
    this.axiosRequestConfig = this.computeAxiosRequestConfig(axiosRequestConfig, options);
    console.log("axiosRequestConfig", this.axiosRequestConfig);

    this.axiosInstance = axios.create(this.axiosRequestConfig);

    this.setupInterceptors(); //
  }

  private computeAxiosRequestConfig(
    config: FullExpandRequestConfig,
    options: RequestOptions
  ): FullExpandRequestConfig {
    Object.assign(config.requestOptions, options);
    return config;
  }
  private handleResponseError(response: any): void {}

  private setupInterceptors(): void {
    // 请求拦截器
    this.axiosInstance.interceptors.request.use(
      (config: FullExpandRequestConfig) => {
        // const requestOptions = config.requestOptions

        console.log("config", config);

        if (config.requestOptions.header) {
          config.headers = {
            ...config.headers,
            ...config.requestOptions.header,
          };
        }

        // console.log('config', config);

        // (config.headers["Content-Type"] = requestOptions.contentType);

        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );

    // 响应拦截器
    this.axiosInstance.interceptors.response.use(
      (response) => {
        return response;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
  }

  /**
   *
   * @param requestParams  url methods data params等配置
   * @param options  自定义请求配置 如header等等
   * @returns
   */
  request(requestParams: RequestParams, options?: RequestOptions) {
    const { url, method, data, ...restParams } = requestParams;

    return new Promise<any>((resolve, reject) => {
      const config: ExpandRequestConfig = {
        url,
        method,
        ...restParams,
        requestOptions: options, // axios auto deep marge
      };
      if (method === RequestMethodEnum.GET) {
        config.params = data;
      } else {
        config.data = data;
      }

      this.axiosInstance
        .request(config)
        .then((res) => {
          resolve(res.data);
        })
        .catch((error) => {
          reject(error.response || error);
        });
    });
  }

  get(requestParams: Omit<RequestParams, "method">, options?: RequestOptions) {
    return this.request(
      {
        ...requestParams,
        method: RequestMethodEnum.GET,
      },
      options
    );
  }

  post(requestParams: Omit<RequestParams, "method">, options?: RequestOptions) {
    return this.request(
      {
        ...requestParams,
        method: RequestMethodEnum.POST,
      },
      options
    );
  }

  put(requestParams: Omit<RequestParams, "method">, options?: RequestOptions) {
    return this.request(
      {
        ...requestParams,
        method: RequestMethodEnum.PUT,
      },
      options
    );
  }

  delete(requestParams: Omit<RequestParams, "method">, options?: RequestOptions) {
    return this.request(
      {
        ...requestParams,
        method: RequestMethodEnum.DELETE,
      },
      options
    );
  }
}

export default Request;
